using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.IO;

namespace Shifter
{
    public partial class mainForm : Form
    {
        //members
        //private bool m_rulesParsed;
        private bool m_ruleLoaded;
        private IParser m_xmlParser;
        private List<Rule> m_parsedRules;
        private Dictionary<String, ModyfiedRuleStep> m_modyfiedRules;
        private Rule m_backupRule;

        private String m_filePath;

        public mainForm()
        {
            InitializeComponent();
            //m_rulesParsed = false;
            m_ruleLoaded = false;
            m_modyfiedRules = new Dictionary<string, ModyfiedRuleStep>();
            m_backupRule = new Rule("Undefined");
            //try
            //{
            //    Console.WriteLine("work environment");
            //    //initParser(@"C:\SFP\Shifter\FlexiFDRULES_shifter.xml");
            //    initParser(@"C:\SFP\Shifter\FlexiFDRULES.xml");
            //}
            //catch
            //{
            //    Console.WriteLine("home environment");
            //    initParser(@"D:\SFP\repo\FlexiFDRULES_shifter.xml");
            //}

        }

        private void initParser(string filePath)
        {
            Console.WriteLine("Initializing Parser: " + filePath);
            m_xmlParser = new Parser(filePath);
            m_parsedRules = m_xmlParser.ParseXML();

            rulesTree.Nodes.Clear(); //clear ruleTree in case of multiple file loads
            foreach (Rule rule in m_parsedRules)
            {
                rulesTree.Nodes.Add(rule.Name, rule.Name);
            }

            Console.WriteLine("Rules in tree: {0}", rulesTree.Nodes.Count);

            //m_rulesParsed = true;
            //TODO: display file icon here
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            Console.WriteLine("load clicked");

            OpenFileDialog openFile = new OpenFileDialog();
            //openFile.FileName = "FlexiFDRULES.xml";
            openFile.Filter = "FlexiFDRULES file|*.xml";
            
            //openFile.InitialDirectory = System.Environment.CurrentDirectory;
            openFile.RestoreDirectory = true;

            DialogResult result = openFile.ShowDialog();
            Console.WriteLine("dialogResult: " + result.ToString());
            if( DialogResult.OK == result )
            {
                m_filePath = openFile.FileName.ToString();
                initParser(m_filePath);
            }

            openFile.Dispose();
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            Console.WriteLine("exit clicked");
            Application.Exit();
        }

        private void txtDrop_DragEnter(object sender, DragEventArgs e)
        {
            Console.WriteLine("Dragged...");
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Copy;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void txtDrop_DragDrop(object sender, DragEventArgs e)
        {
            Console.WriteLine("...and Dropped");
            string[] dropArgs = (string[])e.Data.GetData(DataFormats.FileDrop);
            initParser( dropArgs[0] );
        }

        private void RulesDataGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                if (2 < e.ColumnIndex)
                {
                    Console.WriteLine("row: {0}, column: {1}", e.RowIndex, e.ColumnIndex);
                    DataGridViewCell cell = RulesDataGrid.Rows[e.RowIndex].Cells[e.ColumnIndex];
                    cell.Selected = false;
                    int val = (int)cell.Value;
                    Console.WriteLine("Cell val: " + val);

                    switch (val)
                    {
                        case -2:
                            Console.WriteLine("next");
                            RulesDataGrid.Rows[e.RowIndex + 1].Cells[e.ColumnIndex].Selected = true;
                            if (0 < RulesDataGrid.FirstDisplayedScrollingRowIndex)
                            {
                                RulesDataGrid.FirstDisplayedScrollingRowIndex++;
                            }
                            break;

                        case -1:
                            Console.WriteLine("end");
                            break;

                        default:
                            List<RuleStep> tempList = (List<RuleStep>)RulesDataGrid.DataSource;
                            int index = tempList.FindIndex(new RuleStepPredicate(val).Match);
                            //int index = tempList.FindIndex(x => x.StepNumber == val); //lambda expressions not supported in C# VS2005
                            RulesDataGrid.Rows[index].Selected = true;
                            RulesDataGrid.FirstDisplayedScrollingRowIndex = index-1;
                            Console.WriteLine("found: " + index);
                            break;
                    }
                }
            }
            catch
            {
                Console.WriteLine("catch: header clicked");
            }
        }

        private void btnShiftDown_Click(object sender, EventArgs e)
        {
            int shiftVal = 1;

            if (m_ruleLoaded)
            {
                int currentID = (int)RulesDataGrid.SelectedRows[0].Cells[0].Value;
                List<RuleStep> tempList = (List<RuleStep>)RulesDataGrid.DataSource;
                int index = tempList.FindIndex(new RuleStepPredicate(currentID).Match);
                //int index = tempList.FindIndex(x => x.StepNumber == currentID); //lambda expressions not supported in C# VS2005

                Console.WriteLine("tempList[{0}]: {1}\r\nbackup[{0}]: {2}", index, tempList[index].StepNumber, m_backupRule.RuleStepList[index].StepNumber);

                int spot = findFreeSpace(index, tempList, shiftVal);

                for (int i = spot; i >= index; --i)
                {
                    updateJumpValues(tempList[i].StepNumber, shiftVal, tempList);
                    tempList[i].StepNumber += shiftVal;
                }

                RulesDataGrid.DataSource = tempList;
                RulesDataGrid.Refresh();
            }
        }

        //TODO: private void btnShiftUp...

        private int findFreeSpace(int startIndex, List<RuleStep> list)
        {
            return findFreeSpace(startIndex, list, 1);
        }

        private int findFreeSpace(int startIndex, List<RuleStep> list, int count)
        {
            int retVal = list.Count - 1;
            int ID = list[startIndex].StepNumber;
            ++startIndex;

            for (; startIndex < list.Count; ++startIndex)
            {
                if (ID + count < list[startIndex].StepNumber)
                {
                    retVal = startIndex - 1;
                    break;
                }
                ++ID;
            }

            return retVal;
        }

        private void updateJumpValues(int valueToUpdate, int shift, List<RuleStep> list)
        {
            foreach (RuleStep x in list)
            {
                if (x.FalseStep == valueToUpdate)
                {
                    x.FalseStep += shift;
                }

                if (x.TrueStep == valueToUpdate)
                {
                    x.TrueStep += shift;
                }
            }
        }

        private void rulesTree_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            String chosedNodeName = e.Node.Text;
            Rule chosedRule = m_parsedRules.Find(new RulePredicate(chosedNodeName).Match);
            //Rule chosedRule = m_parsedRulesList.Find(x => x.Name.Equals(chosedNodeName)); //lambda expressions not supported in C# VS2005

            RulesDataGrid.DataSource = chosedRule.RuleStepList;
            m_backupRule = new Rule(chosedRule);
            m_ruleLoaded = true;
        }

        private void btnInsert_Click(object sender, EventArgs e)
        {
            //int offset = 1; //will be user provided value in the future

            //int currentID = (int)RulesDataGrid.SelectedRows[0].Cells[0].Value;

            //List<RuleStep> tempList = (List<RuleStep>)RulesDataGrid.DataSource;
            //int index = tempList.FindIndex(x => x.StepNumber == currentID);
            //tempList.Insert(index, new RuleStep());

            //RulesDataGrid.DataSource = tempList;
            //RulesDataGrid.Refresh();
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (m_ruleLoaded)
            {
                String line;
                List<RuleStep> modyfiedRuleSteps = (List<RuleStep>)RulesDataGrid.DataSource;
                FileStream rulesFileStream = new FileStream(m_filePath, FileMode.Open, FileAccess.ReadWrite);
                StreamReader rulesFileReader = new StreamReader(rulesFileStream);
                StreamWriter rulesFileWriter = new StreamWriter(rulesFileStream);

                while ((line = rulesFileReader.ReadLine()) != null)
                {
                    if (line.Contains("(RULE " + m_backupRule.Name))
                    {
                        Console.WriteLine("found RuleName");
                        long temp = rulesFileWriter.BaseStream.Position;
                        Console.WriteLine("postion in writer: {0}", temp.ToString());
                        break;
                    }
                }

                //for (int i = 0; i < modyfiedRuleSteps.Count; ++i)
                //{
                //    rulesFileWriter.AutoFlush = true;
                //    rulesFileWriter.WriteLine(modyfiedRuleSteps[i].Routine);
                //}

                String retVal = m_xmlParser.FindRule(m_backupRule.Name);

                Console.WriteLine("save OK");
                Console.WriteLine("RetVal:");
                Console.WriteLine("{0}", retVal);

                for (int i = 0; i < modyfiedRuleSteps.Count; ++i)
                {
                    if (m_backupRule.RuleStepList[i] == modyfiedRuleSteps[i])
                    {
                        Console.WriteLine("same");
                    }
                    else
                    {
                        Console.WriteLine("diff");
                    }
                }

                rulesFileWriter.Close();
                rulesFileReader.Close();
                rulesFileStream.Close();
            }
            else
            {
                Console.WriteLine("save NOK");
            }
        }

    }
}


/*
while((line = file.ReadLine()) != null)
{
    if ( line.Contains("word") )
    {
        Console.WriteLine (counter.ToString() + ": " + line);
    }

   counter++;
}

 * 
 */